#include "aktazo.h"

#include <iostream>
#include <sstream>

#include "document_exceptions.h"
#include "menu.h"
#include "document.h"
#include "order.h"
#include "bill.h"
#include "claim.h"
#include "tender.h"
#include "data_io.h"

///body file to implement states of Aktazo

Aktazo::Aktazo() throw(Aktazo_exceptions) : f_in(new std::ifstream), f_out(new std::ofstream), filename("adatok.dat"), v_ptr(new std::vector<Document*>)
{
	try
	{
		load_data();
		run();
		save_data();
	}
	catch(...)
	{
		throw;
	}
}

Aktazo::~Aktazo() throw()
{
	///close files if they are still open
	if(0!=f_in)
	{
		if(f_in->is_open())
		{
			f_in->close();
		}
		delete f_in;
	}
	if(0!=f_out)
	{		
		if(f_out->is_open())
		{
			f_out->close();
		}
		delete f_out;
	}
}

void Aktazo::load_data() throw(File_IO_exceptions)
{
	std::clog<<"Adatfajl beolvasasa: ";
	f_in->open(filename.c_str());
	if(0==f_in || f_in->fail())
	{
		File_IO_exceptions file_read_error("Nem nyithato meg olvasasra.");
		throw file_read_error;
	}
	int i=0;
	///counter for successfully read records, increment after reading
	int k=1;
	///divisor for counter: 1, 10, 100 etc.
	int j=0;
	///counter for tried reading of records, increment before readning
	try
	{
		while(!f_in->eof())
		{
			++j;
			///increment before reading
			int p_type;
			p_type=Data_IO::get_natural(*f_in);
			Document* d;
			switch(p_type)
			{
				case Document::ORDER:
				{
					d=new Order;
					break;
				}
				case Document::BILL:
				{
					d=new Bill;
					break;
				}
				case Document::CLAIM:
				{
					d=new Claim;
					break;
				}
				case Document::TENDER:
				{
					d=new Tender;
					break;
				}
				default:
				{
					Document_exceptions invalid_document_type("Ervenytelen irattipus az adatfajlban.");
					throw invalid_document_type;
					break;
				}
			}
			d->fill_in_document_data(*f_in);
			v_ptr->push_back(d);
			++i;
			///if control reaches this line, it means no exception thus successfull reading
			if(i==10*k)
			{
				///prints a '+' sign when reading
				///the 10th, 100th, 1000th etc. record
				std::cout<<'+';
				k=10*k;
			}
			else if(0 ==i%k)
			{
				///prints a '.' sign when reading the
				///1,2..9th, 20,30..90th, 200,300..900th record
				std::cout<<'.';
			}
		}
	}
	catch(Document_exceptions e)
	{
		std::stringstream record_error;
		record_error<<"Hibas irattipus: #"<<j<<".";
		File_IO_exceptions data_structure_error(record_error.str());
		throw data_structure_error;
	}
	catch(File_IO_exceptions e)
	{
		if(0==i && 1==j)
		{
		}
		else
		{
			std::stringstream record_error;
			record_error<<"Hibas rekord: #"<<j<<".";
			File_IO_exceptions data_structure_error(record_error.str());
			throw data_structure_error;
		}
	}
	catch(...)
	{
		throw;
	}
	f_in->close();
	v_old_size=v_ptr->size();
	///number of read recors
	std::cout<<" "<<v_old_size<<" rekord beolvasva."<<std::endl;
}

void Aktazo::run() throw()
{
	Menu menu(v_ptr);
}

void Aktazo::save_data() throw(File_IO_exceptions)
{
	v_new_size=v_ptr->size();
	///number of all stored recors
	if(v_new_size!=v_old_size)
	{
		///at least one new record to save
		std::cout<<"Mentes."<<std::endl;
		std::clog<<"Uj rekordok rogzitese: ";
		f_out->open(filename.c_str(),std::ios::app);
		if(0==f_out || f_out->fail())
		{
			File_IO_exceptions file_write_error("Nem nyithato meg irasra.");
			throw file_write_error;
		}
		int ii=0;
		///counter for written records
		int k=1;
		///divisor for counter: 1, 10, 100 etc.
		for(unsigned int i=v_old_size;i<v_new_size;++i)
		{
			ii=i-v_old_size;
			if(0!=i)
			{
				(*f_out)<<std::endl;
			}
			v_ptr->at(i)->print_out_document_data(*f_out);
			++ii;
			if(ii==10*k)
			{
				///prints a '+' sign when writing the
				///10th, 100th, 1000th etc. record
				std::cout<<'+';
				k=10*k;
			}
			else if(0 ==ii%k)
			{
				///prints a '.' sign when writing the
				///1,2..9th, 20,30..90th, 200,300..900th record
				std::cout<<'.';
			}
		}
		f_out->close();
		std::cout<<" "<<v_new_size-v_old_size<<" uj rekrord rogzitve, "<<v_new_size<<" osszesen."<<std::endl;
	}
	std::cout<<"Kilepes."<<std::endl;
}
